// 1 导入react
import React from 'react'
import ReactDOM from 'react-dom'

// 引入css文件
import "./index.css"

// 虚拟DOM 和Diff算法

// React 更新视图的思想是: 只要state变化就重新渲染视图
// 特点:思路清晰
// 问题:组件中只有一个DOM元素需要更新时,也要把整个组件的内容重新渲染到页面中?
// 理想状态:部分更新 只更新变化的地方
// 问题: React是如何做到部分更新的?



// 虚拟DOM:本质上就是一个JS对象 ,来用描述你希望在屏幕上看到的内容(UI)


// 执行过程
// 1. 初次渲染时, React会根据初始化state (Modle) 创建一个虚拟DOM对象 (树)
// 2. 根据虚拟DOM 生成真正的DOM 渲染到页面中
// 3. 当数据变化后(setState()) 重新根据新的数据 创建新的虚拟DOM对象(树)
// 4. 与上一次得到的虚拟DOM对象,使用Diff算法对比 找不同 得到需要更新的内容
// 5. 最终, React 只将变化的内容更新 (patch) 到DOM 中 ,重新渲染到页面
// 6. 虚拟DOM->state+JSX
// 7. 虚拟DOM 的真正的价值从来都不是性能
// 8. 虚拟DOM 可以跨平台


// 总结
// 1. 工作角度 应用第一 原理第二
// 2. 原理有助于更好的理解React的自身运行机制
// 3. setState() 异步更新数据
// 4. 父组件的更新导致子组件更新,纯组件提升性能
// 5. 思路清晰简单为前提 虚拟DOM和Diff保证效率

// 代码演示
// 组件render()调用后 根据状态和JSX结构生成虚拟DOM对象
// 只更新变化的内容
const obj = { number: 0 }
const newObj = obj
newObj.number = 23
console.log(newObj.number === obj.number)

class App extends React.Component {
    state = {
        count: 0,
        obj: { number: 0 }
    }

    // 错误演示

    // handlerClick = (e) => {
    //     this.setState((state, props) => {

    //         const newObj = this.state.obj
    //         newObj.number = Math.floor(Math.random() * 3)
    //         return {
    //             count: state.count + 1,
    //             obj: newObj
    //         }
    //     })
    // }

    handlerClick = (e) => {
        const newObj = { ...this.state.obj, number: Math.floor(Math.random() * 3) }
        // const list = [...this.state.list, {Math.floor(Math.random() * 3) }]
        this.setState((state, props) => {
            return {
                count: state.count + 1,
                obj: newObj
            }
        })
    }

    // 钩子函数
    // 因为两次生成的随机数可能相同 如果相同不需要重新渲染
    // shouldComponentUpdate(nextProps, nextState) {
    //     console.log('最新的state', nextProps)
    //     console.log('this.props', this.props)
    //     // return false 阻止页面渲染
    //     console.log(this.state.number)
    //     console.log(nextState.number)
    //     return nextState.number !== this.state.number
    // }


    // render方法调用 并不意味着浏览器重新渲染!!
    // render方法调用 仅仅说明要进行diff过程 
    render() {
        console.log("reder")
        const el = (
            <div>
                <h1>随机数: {this.state.obj.number}</h1>
                <button onClick={this.handlerClick}>重新生成</button>
            </div>
        )
        console.log("虚拟DOM ", el)
        return el
    }
}


class NumberBox extends React.Component {



    state = {
        obj: { number: 0 }
    }
    shouldComponentUpdate(nextProps, nextState) {
        console.log('最新的state', nextProps)
        console.log('this.props', this.state)
        // return false 阻止页面渲染
        console.log(this.state.obj.number)
        console.log(nextProps.obj.number)
        return nextProps.obj !== this.state.obj
    }
    render() {
        console.log("reder")
        return <h1>随机数: {this.props.obj.number}</h1>
    }

    componentDidMont() {
        this.setState((preState, props) => {
            return {
                obj: props.obj
            }
        })
    }
}

//3 渲染react元素
ReactDOM.render(
    <App />,
    document.getElementById('root'))
